%%%-------------------------------------------------------------------
%%% @author iamapo
%%% @copyright (C) 2014, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 05. Nov 2014 17:21
%%%-------------------------------------------------------------------
-module(nachrichtendienst).
-author("iamapo").
-import(werkzeug, [get_config_value/2, logging/2, timeMilliSecond/0, to_String/1]).
-export([getNachrichten/4]).
-compile(export_all).

%% API
-export([]).
%antworted client auf getmessage
getNachrichten(SenderPID, Clientlist, DLQ, ClientLifeTime) ->
  %check ob client schon bekannt
  case contains(SenderPID, proplists:get_keys(Clientlist)) of
    true ->
      %holt tupel des Clients
      {Key, {NNR, Timer}} = lists:keyfind(SenderPID, 1, Clientlist),
      %loescht tupel des clients
      NewClientList = proplists:delete(Key, Clientlist),
      %reseted Timer
      ResettedTimer = werkzeug:reset_timer(Timer, ClientLifeTime, {clienttimeout, SenderPID}),
      %holt nachricht
      [NextMessageID, Message] = getNextMessageForClient(NNR, DLQ),
      %erzeugt flag
      Terminated = NextMessageID >= dlq:getMaxNumber(DLQ),
      werkzeug:logging("NServer.log", lists:concat([Message, "Server: Nachrichtennummer ", to_String(NextMessageID), " an ", to_String(SenderPID), " gesendet\n"])),
      %sendet an Client
      SenderPID ! {reply, NextMessageID, Message, Terminated},
      %neuer eintrag fuer client
      NewClientlist2 = [{Key, {NextMessageID, ResettedTimer}} | NewClientList],
      %return
      NewClientlist2;

  % Erste Anfrage dieses Clients.
    false ->
      %kleinste nummer aus der dlq holen
      NNR = dlq:getMinNumber(DLQ),
      %zugehoerige nachricht holen
      Message = dlq:get(NNR, DLQ),
      %erzeugt timer für client
      {_, Timer} = timer:send_after(ClientLifeTime * 1000, self(), {timerClient, SenderPID}),
      %terminated setzen
      Terminated = NNR >= dlq:getMaxNumber(DLQ),
      werkzeug:logging("NServer.log", lists:concat([Message, "Server: Nachrichtennummer ", to_String(NNR), " an ", to_String(SenderPID), " gesendet\n"])),
      %senden an client
      SenderPID ! {reply, NNR, Message, Terminated},
      %neuer eintrag in die Clientlist
      NewClientlist = [{SenderPID, {NNR, Timer}} | Clientlist],
      %return
      NewClientlist

  end
.

%holt naechste nachricht aus der dlq
%fals in der zwischenzeit eine nachricht aus der dlq gelöscht wurde
%wird kleinste message aus der dlq gesendet
getNextMessageForClient(NNR, DLQ) ->
  NewNNr = NNR + 1,
  Message = dlq:get(NewNNr, DLQ),
  if Message /= messageNotInDLQ ->
    [NewNNr, Message];
    true ->
      getNextMessageForClient(NewNNr, DLQ)
  end
.

contains(_, []) -> false;
contains(Elem, [Head | Tail]) ->
  case Elem == Head of
    true -> true;
    false -> contains(Elem, Tail)
  end.